package com.alivehex.physensor5;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import android.util.Log;

public class DataSource {
	private final int MAX_DATA_NUMBER = 100000;
	
	// private long StartTimeInMs = 0;
//	private ArrayList<Data> dataList;
	private MyObservable notifier = new MyObservable();
	private int MaxNumberOfData;
	private int HeadIndex;
	private int TailIndex;
	private float[] X;
	private float[] Y;
	private int DataCount;
	
	public DataSource() {
		MaxNumberOfData = 1000;
//		dataList = new ArrayList<Data>(MaxNumberOfData);
		HeadIndex = 0;
		TailIndex = 0;
		X = new float[MaxNumberOfData];
		Y = new float[MaxNumberOfData];
		DataCount = 0;
	}
	
	public DataSource(int NumberOfDataLimit) {
		MaxNumberOfData = NumberOfDataLimit;
		HeadIndex = 0;
		TailIndex = 0;
//		dataList = new ArrayList<Data>(MaxNumberOfData);
		if(NumberOfDataLimit == -1) {
			NumberOfDataLimit = MAX_DATA_NUMBER;
		}
		X = new float[MaxNumberOfData];
		Y = new float[MaxNumberOfData];
		DataCount = 0;
	}
	
//	private class Data {
//		public float XValueInSecond;
//		public float YValue;
//		
//		public Data(float XSecond, float Y) {
//			XValueInSecond = XSecond;
//			YValue = Y;
//		}
//	}
	
	// encapsulates management of the observers watching this datasource for update events:
    private class MyObservable extends Observable {
	    @Override
	    public void notifyObservers() {
	        setChanged();
	        super.notifyObservers();
	    }
    }
    
    public void clear() {
//    	dataList.clear();
    	HeadIndex = 0;
		TailIndex = 0;
    }
    
    public int addData2(float YValue, float XValueInMs) {
    	return addData(YValue, XValueInMs * 1000);
    }
    
    public int addData(float YValue, float XValueInSecond) {
//    	Data data = new Data(YValue, XValueInSecond);
    	int index = TailIndex;
    	
//    	dataList.set(TailIndex, data);
    	X[TailIndex] = XValueInSecond;
    	Y[TailIndex] = YValue;
    	DataCount ++;
    	
//    	Log.d("ADD", "Tail=" + Integer.toString(TailIndex) + 
//    				 "Head=" + Integer.toString(HeadIndex) +
//    				 "X="	 + Float.toString(XValueInSecond) +
//    				 "Y="	 + Float.toString(YValue)); 
    	
    	TailIndex = (TailIndex + 1) % MaxNumberOfData;
    	if(TailIndex == HeadIndex) {
    		HeadIndex = (HeadIndex + 1) % MaxNumberOfData;
    	}
    	
		return index;	// dataList.indexOf(data);
    }
    
    public void updateData() {
    	notifier.notifyObservers();
    }
    
//    public void removeData(int index) {
//    	dataList.remove(index);
//    }
    
    public int getItemCount() {
//    	int Count = (DataCount >= (MaxNumberOfData - 1)) ? (MaxNumberOfData - 1) : DataCount;
    	
//    	Log.d("TOTAL", Integer.toString(Count));
    	
    	// return MaxNumberOfData; // dataList.size();
    	return (DataCount >= (MaxNumberOfData - 1)) ? (MaxNumberOfData - 1) : DataCount;
    }
    
    public Number getX(int index) {
//    	return dataList.get((HeadIndex + index) % MaxNumberOfData).XValueInSecond;
    	// return (dataList.get(index).GetXFloat() - (float)StartTimeInMs) / (float)1000;
//    	float XValue = X[(HeadIndex + index) % MaxNumberOfData];
//    	float HeadValue = X[HeadIndex];
//    	float DeltaSec = (XValue - HeadValue) / 1000;
    	
//    	Log.d("getX", "X[" + Integer.toString(index) + "]" +
//    				  "=" + Float.toString(XValue) +
//    				  "Head=" + Float.toString(HeadValue) +
//    				  "DeltaSec=" + Float.toString(DeltaSec));
    	
    	return (X[(HeadIndex + index) % MaxNumberOfData] - X[HeadIndex]) / 1000;
    }
    
    public Number getXRaw(int index) {
    	return X[(HeadIndex + index) % MaxNumberOfData] / 1000;
    }
    
    public Number getY(int index) {
//    	float YValue = Y[(HeadIndex + index) % MaxNumberOfData];
    	
//    	Log.d("getY", "Y[" + Integer.toString(index) + "]" +
//				  	  "=" + Float.toString(YValue));
//		if (index > dataList.size()) {
//    		throw new IllegalArgumentException();
//    	} 
//		return dataList.get(index).Y;
//    	return dataList.get((HeadIndex + index) % MaxNumberOfData).YValue;
    	return Y[(HeadIndex + index) % MaxNumberOfData];
    }
    
    public void addObserver(Observer observer) {
        notifier.addObserver(observer);
    }
 
    public void removeObserver(Observer observer) {
        notifier.deleteObserver(observer);
    }
}
